package com.maiko.usercenter.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * 全局 Web 配置类
 * - 跨域配置
 * <p>
 * 配置类加上 @Configuration注解用于定义配置，拦截器可以通过配置类注册到Spring MVC中
 * <p>
 * 流程：
 * 1. 首先，Spring容器初始化，会扫描并加载所有的配置类（带有 @Configuration 注解的类），将配置信息加载到Spring容器中。
 * 2. 在Spring容器初始化的过程中，会初始化并注册拦截器，通过在配置类中定义 @Bean 的方式将拦截器加入Spring容器。
 * 3. Spring MVC会初始化 DispatcherServlet，它是Spring MVC的入口，负责请求的分发和处理。
 * 4. DispatcherServlet 会加载WebApplicationContext，即由配置类定义的Spring容器。此时会将拦截器等配置信息也加载进来。
 * 5. 当有请求进来时，会由 DispatcherServlet 接收并处理。
 * 6. 请求进入 DispatcherServlet 后，会先经过拦截器链。拦截器链中的拦截器按照配置顺序执行，可以对请求进行预处理、后处理等操作。
 * 7. 经过拦截器链处理后，请求会进入 DispatcherServlet 的分发流程，根据请求的路径匹配相应的Controller进行处理。
 * 8. 根据请求路径匹配到对应的Controller，Controller负责业务逻辑的处理，生成响应。
 * 9. Controller处理请求后，会返回一个视图名，Spring MVC会使用视图解析器解析这个视图名，得到具体的视图。
 * 10.最终，DispatcherServlet会将处理后的结果渲染到具体的视图上，并返回给客户端。
 *
 * @author: Maiko7
 * @create: 2025-07-13 9:00
 */
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                /**
                 * 当allowCredentials为true时，allowedOrigins不能为星号，需为具体的ip地址【如果接口不带cookie,ip无需设成具体ip】
                 * 为什么？
                 * 浏览器的安全策略规定：
                 * 如果允许前端 JS 脚本带上 Cookie（或其他凭证）跨域访问，服务器必须显式指定允许的源（Origin），不能写 *，否则浏览器会拒绝。
                 * 这是为了防止跨站请求伪造（CSRF）等安全风险。
                 */
                .allowedOrigins("http://localhost:9527", "http://127.0.0.1:9527", "http://127.0.0.1:8082", "http://127.0.0.1:8083")
                // .allowedOrigins("*")
                // 允许发送 Cookie
                .allowCredentials(true)
                // 设置允许的方法
                // .allowedMethods("GET", "POST", "DELETE", "PUT", "PATCH", "OPTIONS", "HEAD")
                .allowedMethods("*")
                /**
                 * 跨域允许时间 预检请求缓存时间 1 小时
                 * .maxAge(3600) 是跨域请求中 预检请求（Preflight Request） 的缓存时间设置，单位是秒，意思是浏览器在1个小时内不会重复发预检请求，能提高跨域请求性能。
                 *
                 * 什么是预检请求？
                 * 当浏览器发起跨域请求，尤其是使用了非简单请求方法（PUT、DELETE、POST 的特定 Content-Type 等）或者携带自定义头时，浏览器会先发一个 OPTIONS 请求，叫“预检请求”。
                 *
                 * 预检请求用于询问服务器：
                 * “我想用这种方法、带这些头跨域访问，可以吗？”
                 * 服务器回复允许后，浏览器才会真正发实际请求。
                 *
                 * .maxAge(3600) 做了什么？
                 * 它告诉浏览器：
                 * “这次预检的结果可以缓存3600秒（1小时），这期间你不必再发预检请求了，直接发实际请求。”
                 *
                 * 举个例子
                 * 假设你有个前端页面，频繁调用接口 /api/data，用的是 PUT 方法（属于需要预检的请求）。
                 * 浏览器第一次调用时，会先发一次 OPTIONS 预检请求。
                 * 服务器响应允许。
                 * 这次预检结果在浏览器缓存了 3600 秒。
                 * 这 1 小时内，浏览器再调用 /api/data 的 PUT 请求时，就不会再发 OPTIONS 预检，直接发请求，性能更好，响应更快。
                 *
                 * 如果不设置 maxAge 或值很小？
                 * 浏览器会频繁发预检请求，增加网络请求次数，浪费资源和时间。
                 *
                 */
                .maxAge(3600);
    }

}
